﻿//  -------------------- iSharePoint -------------------- //
// 
//  Company:	IT Complex, LLC
//  Project:	Smart.Common
//  File name:	XmlRuleChecker.cs
//  Developer:	Solomatov Igor
//  Created:	15.04.2012
// 
//  -------------------- iSharePoint -------------------- //

using System;

namespace Smart.Common.Rules
{
	/// <summary>
	/// Xml rule checker
	/// </summary>
	public class XmlRuleChecker : RuleChecker
	{
		/// <summary>
		/// Xml rule checker
		/// </summary>
		public XmlRuleChecker(RulesCtx ctx)
			: base(ctx)
		{
		}

		/// <summary>
		/// Check rule's condition, checks only single condition
		/// </summary>
		/// <typeparam name="TRuleConditionType">Type of rule's condition</typeparam>
		/// <param name="condition">Rule's condition</param>
		/// <returns>Tested whether the condition</returns>
		public override bool IsConditionFullfilled<TRuleConditionType>(TRuleConditionType condition)
		{
			var ruleCondition = condition as XmlRuleCondition;

			if (ruleCondition == null)
				throw new ArgumentNullException("condition");

			bool res;
			bool handled;

			switch (ruleCondition.Operator)
			{
				case ComparisonOperator.Eq:
					return H.CompareValue(Ctx.Variables.SafeGet(ruleCondition.Left), ruleCondition.Right) == 0;

				case ComparisonOperator.Neq:
					return H.CompareValue(Ctx.Variables.SafeGet(ruleCondition.Left), ruleCondition.Right) != 0;

				case ComparisonOperator.Leq:
					return H.CompareValue(Ctx.Variables.SafeGet(ruleCondition.Left), ruleCondition.Right) <= 0;

				case ComparisonOperator.Geq:
					return H.CompareValue(Ctx.Variables.SafeGet(ruleCondition.Left), ruleCondition.Right) >= 0;

				case ComparisonOperator.Lt:
					return H.CompareValue(Ctx.Variables.SafeGet(ruleCondition.Left), ruleCondition.Right) < 0;

				case ComparisonOperator.Gt:
					return H.CompareValue(Ctx.Variables.SafeGet(ruleCondition.Left), ruleCondition.Right) > 0;

				case ComparisonOperator.Function:
					res = ExecuteFunction(ruleCondition.Function, out handled);

					if (!handled)
						throw new NotSupportedException("singleCondition.Function: " + ruleCondition.Function.Name);

					return res;

				default:
					throw new ArgumentOutOfRangeException("condition");
			}
		}

		/// <summary>
		/// Executes condition function
		/// </summary>
		/// <param name="function">Function info</param>
		/// <param name="handled">true, if handled</param>
		/// <returns>function result</returns>
		public virtual bool ExecuteFunction(XmlRuleConditionFunction function, out bool handled)
		{
			if (function.Name.EqIC("Any"))
			{
				handled = true;

				return true;
			}

			handled = false;
			return false;
		}
	}
}